#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;
const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;
char *gargv[argvnum];
int gargc = 0;
char pwd[basesize];
char pwdenv[basesize];
char *genv[envnum];
string GetUserName()
{
  string name = getenv("USER");
  return name.empty() ? "None" : name;
}
string GetHostName()
{
  string hostname = getenv("HOSTNAME");
  return hostname.empty() ? "None" : hostname;
}
string GetPwd()
{
  if(nullptr == getcwd(pwd,sizeof(pwd))) return "None";
  snprintf(pwdenv,sizeof(pwdenv),"PWD=%s",pwd);
  putenv(pwdenv);
  return pwd;
  //string pwd = getenv("PWD");
  //return pwd.empty() ? "None" : pwd;
}
string MakeCommandLine()
{
  char command_line[basesize];
  snprintf(command_line,basesize,"[%s@%s %s]# ",\
      GetUserName().c_str(),GetHostName().c_str(),GetPwd().c_str());
  return command_line;
}
void PrintCommandLine()
{
  printf("%s",MakeCommandLine().c_str());
  fflush(stdout);
}
bool GetCommandLine(char command_buffer[],int size)
{
  char* result = fgets(command_buffer,size,stdin);
  if(result == nullptr)
    return false;
  command_buffer[strlen(command_buffer)-1] = 0;
  if(strlen(command_buffer) == 0)return false;
  return true;
}
void ParseCommandLine(char command_buffer[],int len)
{
  (void)len;
  memset(gargv,0,sizeof(gargv));
  gargc = 0;
  const char *sep = " ";
  gargv[gargc++] = strtok(command_buffer,sep);
  while((bool)(gargv[gargc++] = strtok(nullptr,sep)));//切割所有字符串
  gargc--;
}
void debug()
{
  printf("argc: %d\n",gargc);
  for(int i = 0; gargv[i];i++)
  {
    printf("argv[%d]: %s\n",i,gargv[i]);
  }

}
bool ExecuteCommandLine()//执行命令
{
  pid_t id = fork();
  if(id < 0) return false;
  else if(id == 0)
  {
    //1.执行命令
    //execvp(gargv[0],gargv);
    execvpe(gargv[0],gargv,genv);
    //2.退出
    exit(1);
  }
  int status = 0;
  pid_t rid = waitpid(id,&status,0);
  if(rid > 0)
  {
    //
    return true;
  }
  return false;
}
void InitEnv()
{                                                                                                                        
  extern char **environ;
  int index = 0;
  while(environ[index])
  {
    genv[index] = (char*)malloc(strlen(environ[index])+1);
    strncpy(genv[index],environ[index],strlen(environ[index])+1);
    ++index;
   }
   genv[index]= nullptr;
  
}

void AddEnv(const char* item)
{
     int index = 0;
     while(genv[index])                                                                                                  
     {
       index++;
     }
     genv[index] = (char*)malloc(strlen(item)+1);
     strncpy(genv[index],item,strlen(item)+1);
     genv[++index] = nullptr;
}

bool CheckAndExecBuiltCommand()
{
  if(strcmp(gargv[0],"cd") == 0)
  {
    if(gargc == 2)
    {
      chdir(gargv[1]);
    }
    return true;
  }
  else if(strcmp(gargv[0],"export") == 0)
  {
    if(gargc == 2)
    {
      AddEnv(gargv[1]);
    }
    return true;
  }
  else if(strcmp(gargv[0],"env") == 0)
  {
    for(int i = 0; genv[i];i++)
    {
      printf("%s\n",genv[i]);
    }
    return true;
  }
  return false;

}
//void InitEnv()
//{
//  extern char **environ;
//  int index = 0;
//  while(environ[index])
//  {
//    genv[index] = (char*)malloc(strlen(environ[index])+1);
//    strncpy(genv[index],environ[index],strlen(environ[index])+1);
//    ++index;
//  }
//  genv[index]= nullptr;
//  
//}
//void AddEnv(const char* item)
//{
//  int index = 0;
//  while(gargv[index])
//  {
//    index++;
//  }
//  genv[index] = (char*)malloc(strlen(item)+1);
//  strncpy(genv[index],item,strlen(item)+1);
//  genv[++index] = nullptr;
//}
int main()
{
  InitEnv();
  char command_buffer[basesize];
  while(true)
  {
     PrintCommandLine();//打印命令行提示符
     if(!GetCommandLine(command_buffer,basesize))//获取用户命令
     {
       continue;
     }
     //printf("%s\n", command_buffer);
     ParseCommandLine(command_buffer,strlen(command_buffer));//分析命令
     //debug();
     if(CheckAndExecBuiltCommand())
     {
       continue;
     }
     ExecuteCommandLine();//执行命令
  }
  return 0;
}
